package com.wskj.easybuy.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import com.wskj.easybuy.util.ConfigUtil;
import com.wskj.easybuy.util.JDBCUtil;






/**
 * 所有操作数据库的公共的方法 ： 创建连接 关闭连接 执行修改 执行查询 等操作。。。
 * 
 * @author Administrator
 *
 */
public class BaseDao {	
	
	private Connection conn;//连接
	private PreparedStatement stmt;//申明
	private ResultSet rs;//结果集
	
	//开启连接    通过C3P0的数据源进行连接 
	public void getConnection() {	    
		try {		
		/*//Context  ctx=new InitialContext();			
		//DataSource source=(DataSource)ctx.lookup("java:comp/env/jdbc/news");			
		//conn =source.getConnection();		
       */
		conn=ConfigUtil.getConnection();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
			
		
	}		

	/**
	 * 关闭连接的方法 
	 */
	public void closeAll() {
		try {			
			if(rs!=null) rs.close(); // 防止出现 nullpointException
			if(stmt!=null) stmt.close();
		    if(conn!=null) conn.close();			
		} catch (SQLException e) {			
			e.printStackTrace();
		}	
	}
	
	
	/**
	 * 执行所有的修改的操作
	 *    写sql 语句    预编译的， 会用？代替 里面实际参数 
	 *    statement sql 拼接的形式  ： sql注入 
	 *    实际的参数 就是 给 占位符号 ？ 赋值 
	 * @param sql    执行修改的语句  insert  update delete ....
	 * @param params 传递的参数   
	 * @return 
	 */	
	public int executeUpdate(String sql, Object[] params) {
		int count = 0;
		getConnection();
		try {
			// 申明
			stmt = conn.prepareStatement(sql);
			// 给预编译申明中的参数 赋值 ? 提前进行占位符
			// ?---> 赋值1 ?的下标从1 开始 数据的下标从0 开始 。。
			// 传递的参数   与 sql语句中的？是一一对应的
			if (params != null) {
				for (int i = 0; i < params.length; i++) {
					stmt.setObject(i + 1, params[i]);
				}
			}
			// 执行预编译的申明
			count = stmt.executeUpdate();
			// 关闭连接 close
			closeAll();
			return count;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return 0;
		}
	}

	// 公共的查询的方法 不同 表查询的时候 查询的语句 以及查询的参数是不一样的
	// ResultSet --->Entity 进行操作
	/**
	 * 
	 * @param sql 查询的语句 sql  select  .....
	 * @param params  查询的条件参数 
	 * @return  结果集 
	 */
	public ResultSet executeQuery(String sql, Object[] params) {
		getConnection();
		try {
			// 获取申明
			stmt = conn.prepareStatement(sql);
			if (params != null) {

				for (int i = 0; i < params.length; i++) {
					stmt.setObject(i + 1, params[i]);
				}
			}			
			// 执行的是查询的操作 
			rs = stmt.executeQuery();
			// 結果集  处理完成后才能关闭 ....
			return rs;
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	
	// 简化的泛型方法   直接得到实体类型     -- 通过简单的辅助工具   讲 ResultSet 直接转换为实体	
	// 获取所有的 实体集合 	
	/**
	 *  使用BaseDao 方法注意事项:
	 *     1.实体类中的属性名称   与 查询的结果集的名称一一对应的；
	 *     2.无参数的构造方法
	 * 
	 */
	
	
	/**
	 * 根据查询条件 返回多个实体集合 
	 * @param sql 查询的语句
	 * @param params 查询的条件 
	 * @param c  返回实体的类型  
	 * @return
	 */
	public <T> List<T> getAllEntity(String sql,Object[] params,Class<T> c){		
		rs=executeQuery(sql, params);
		List<T> list=JDBCUtil.convertResultSetToList(c, rs);
		 // 结果集操作完成后 关闭 
		closeAll();		
		return list;	
	}
	
	
	/**
	 * 根据条件返回单个的实体
	 * @param sql 查询的语句
	 * @param params 查询的条件 
	 * @param c  返回实体的类型  
	 * @return
	 */	
	public <T> T getSingleEntity(String sql,Object[] params,Class<T> c){		
		rs=executeQuery(sql, params);
		T t=JDBCUtil.convertResultSetToEntity(c, rs);
		closeAll();
		return t;
	}
	
	
	
	/**
	 * 查询条数的方法 
	 * 
	 * 
	 */
	
	public  int getCounts(String sql,Object[] params){
		int counts=0;
		rs=executeQuery(sql, params);
		try {
			rs.next();			
			counts=rs.getInt(1);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			closeAll();
		}
		
		return counts;	
	}

}
